﻿using System;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace Network.Library
{
    /// <summary>
    /// Http协议帮助类
    /// </summary>
    public class HttpProtocolHelper
    {
        static HttpProtocolHelper()
        {
            ServicePointManager.DefaultConnectionLimit = Environment.ProcessorCount * 6;
            ServicePointManager.MaxServicePoints = 0;
            ServicePointManager.Expect100Continue = false;
            ServicePointManager.ServerCertificateValidationCallback = VerifyServerCertificate;
        }

        /// <summary>
        /// 验证远程身份验证的SSL证书
        /// </summary>
        public static event RemoteCertificateValidationCallback ValidationRemoteCertificateEvent;

        /// <summary>
        /// 验证服务器证书,如果不设置验证事件，总是验证成功
        /// </summary>
        /// <param name="sender">一个对象，它包含此验证的状态信息。</param>
        /// <param name="certificate">用于对远程方进行身份验证的证书。</param>
        /// <param name="chain">与远程证书关联的证书颁发机构链。</param>
        /// <param name="errors">与远程证书关联的一个或多个错误。</param>
        /// <returns>确定是否接受指定证书进行身份验证</returns>
        private static bool VerifyServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            if (ValidationRemoteCertificateEvent != null)
            {
                return ValidationRemoteCertificateEvent(sender, certificate, chain, errors);
            }
            return true;
        }

        /// <summary>
        /// 发送同步的Post方法
        /// </summary>
        /// <param name="sUrl">url</param>
        /// <param name="bPostData">post的byte[]数据</param>
        /// <param name="contentType">内容类型,默认：application/json;charset=utf-8</param>
        /// <param name="timeOut">超时时间（单位秒，默认10）</param>
        /// <returns>返回的结果</returns>
        /// <exception cref="T:System.Exception"></exception>               
        public static string SendPostRequestData(string sUrl, byte[] bPostData, string contentType = "application/json;charset=utf-8", int timeOut = 10)
        {
            string sResult = string.Empty;
            HttpWebRequest webRequest = null;

            try
            {
                webRequest = (HttpWebRequest)WebRequest.Create(sUrl);
                webRequest.ProtocolVersion = HttpVersion.Version10;
                webRequest.Timeout = timeOut * 1000;
                webRequest.KeepAlive = false;
                webRequest.Method = "POST";
                webRequest.ContentType = contentType;
                webRequest.Proxy = null;
                webRequest.UserAgent = "Mozilla/5.0";
                webRequest.Headers.Add("Accept-Encoding", "gzip, deflate");

                using (Stream postDataStream = webRequest.GetRequestStream())
                {
                    postDataStream.Write(bPostData, 0, bPostData.Length);
                }

                using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
                {
                    // 如果使用了GZip则先解压
                    if (webResponse.ContentEncoding.ToLower() == "gzip")
                    {
                        using (Stream streamReceive = webResponse.GetResponseStream())
                        {
                            using (var zipStream = new GZipStream(streamReceive, CompressionMode.Decompress))
                            {
                                using (StreamReader sr = new StreamReader(zipStream, Encoding.GetEncoding(webResponse.CharacterSet)))
                                {
                                    sResult = sr.ReadToEnd();
                                }
                            }
                        }
                    }
                    // 如果使用了deflate则先解压
                    else if (webResponse.ContentEncoding.ToLower() == "deflate")
                    {
                        using (Stream streamReceive = webResponse.GetResponseStream())
                        {
                            using (var zipStream = new DeflateStream(streamReceive, CompressionMode.Decompress))
                            {
                                using (StreamReader sr = new StreamReader(zipStream, Encoding.GetEncoding(webResponse.CharacterSet)))
                                {
                                    sResult = sr.ReadToEnd();
                                }
                            }
                        }
                    }
                    // 默认获取数据
                    else
                    {
                        using (Stream streamReceive = webResponse.GetResponseStream())
                        {
                            using (StreamReader sr = new StreamReader(streamReceive, Encoding.GetEncoding("utf-8")))
                            {
                                sResult = sr.ReadToEnd();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                webRequest?.Abort();
                throw ex;
            }

            return sResult;
        }

        /// <summary>
        /// 发送同步的Post方法(指定contentType)
        /// </summary>
        /// <param name="sUrl">url</param>
        /// <param name="sPostData">post的字符串数据</param>
        /// <param name="contentType">内容类型,默认：application/json;charset=utf-8</param>
        /// <returns>返回的结果</returns>
        /// <exception cref="T:System.Exception"></exception>
        public static string SendPostRequestData(string sUrl, string sPostData, string contentType = "application/json;charset=utf-8")
        {
            return SendPostRequestData(sUrl, Encoding.UTF8.GetBytes(sPostData), contentType);
        }

        /// <summary>
        /// 同步获取字符串返回值的Get方法
        /// </summary>
        /// <param name="url">url</param>
        /// <param name="encoding">编码方式（默认为null）</param>
        /// <returns>返回的结果</returns>
        /// <exception cref="T:System.Exception"></exception>       
        /// <exception cref="T:System.ArgumentNullException"></exception>
        public static string SendGetRequestAsString(string url, Encoding encoding = null)
        {
            if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException("url");

            string sResult = string.Empty;
            HttpWebRequest webRequest = null;
            try
            {
                webRequest = (HttpWebRequest)WebRequest.Create(url);
                webRequest.ProtocolVersion = HttpVersion.Version10;
                webRequest.Timeout = 100000;
                webRequest.KeepAlive = false;
                webRequest.Method = "GET";
                webRequest.UserAgent = "Mozilla/4.0";
                webRequest.ContentType = "application/json; encoding=utf-8";
                webRequest.Headers.Add("Accept-Encoding", "gzip, deflate");
                webRequest.Proxy = null;

                using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
                {
                    encoding = encoding == null ? Encoding.UTF8 : encoding;

                    //如果使用了GZip则先解压
                    if (webResponse.ContentEncoding.ToLower() == "gzip")
                    {
                        using (Stream streamReceive = webResponse.GetResponseStream())
                        {
                            using (var zipStream = new GZipStream(streamReceive, CompressionMode.Decompress))
                            {
                                using (StreamReader sr = new StreamReader(zipStream, encoding))
                                {
                                    sResult = sr.ReadToEnd();
                                }
                            }
                        }
                    }
                    //如果使用了deflate则先解压
                    else if (webResponse.ContentEncoding.ToLower() == "deflate")
                    {
                        using (Stream streamReceive = webResponse.GetResponseStream())
                        {
                            using (var zipStream =
                                new DeflateStream(streamReceive, CompressionMode.Decompress))
                            {
                                using (StreamReader sr = new StreamReader(zipStream, encoding))
                                {
                                    sResult = sr.ReadToEnd();
                                }
                            }
                        }
                    }
                    else
                    {
                        using (Stream streamReceive = webResponse.GetResponseStream())
                        {
                            using (StreamReader sr = new StreamReader(streamReceive, encoding))
                            {
                                sResult = sr.ReadToEnd();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                webRequest?.Abort();
                throw ex;
            }
            return sResult;
        }

        /// <summary>
        /// 同步获取字符串返回值的Get方法
        /// </summary>
        /// <param name="url">url</param>
        /// <param name="timeout">超时时间</param>
        /// <param name="encoding">编码方式（默认为UTF8）</param>
        /// <returns>返回的结果</returns>
        public static string SendGetRequestAsString(string url, int timeout, Encoding encoding = null)
        {
            string sResult = string.Empty;
            HttpWebRequest webRequest = null;
            try
            {
                webRequest = (HttpWebRequest)WebRequest.Create(url);
                webRequest.ProtocolVersion = HttpVersion.Version10;
                webRequest.Timeout = timeout;
                webRequest.Method = "GET";
                webRequest.KeepAlive = false;
                webRequest.Proxy = null;
                webRequest.UserAgent = "Mozilla/4.0";
                webRequest.ContentType = "application/json; encoding=utf-8";
                webRequest.Headers.Add("Accept-Encoding", "gzip, deflate");

                using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
                {
                    encoding = encoding == null ? Encoding.UTF8 : encoding;

                    //如果使用了GZip则先解压
                    if (webResponse.ContentEncoding.ToLower() == "gzip")
                    {
                        using (Stream streamReceive = webResponse.GetResponseStream())
                        {
                            using (var zipStream = new GZipStream(streamReceive, CompressionMode.Decompress))
                            {
                                using (StreamReader sr = new StreamReader(zipStream, encoding))
                                {
                                    sResult = sr.ReadToEnd();
                                }
                            }
                        }
                    }
                    //如果使用了deflate则先解压
                    else if (webResponse.ContentEncoding.ToLower() == "deflate")
                    {
                        using (Stream streamReceive = webResponse.GetResponseStream())
                        {
                            using (var zipStream =
                                new DeflateStream(streamReceive, CompressionMode.Decompress))
                            {
                                using (StreamReader sr = new StreamReader(zipStream, encoding))
                                {
                                    sResult = sr.ReadToEnd();
                                }
                            }
                        }
                    }
                    else
                    {
                        using (Stream streamReceive = webResponse.GetResponseStream())
                        {
                            using (StreamReader sr = new StreamReader(streamReceive, encoding))
                            {
                                sResult = sr.ReadToEnd();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {

                webRequest?.Abort();
                throw ex;
            }
            return sResult;
        }

        /// <summary>
        /// 同步获取Byte[]返回值的Get方法
        /// </summary>
        /// <param name="url"></param>
        /// <param name="encoding"></param>
        /// <returns>处理结果</returns>
        public static byte[] SendGetRequestAsByte(string url, Encoding encoding = null)
        {
            byte[] sResult = null;
            HttpWebRequest webRequest = null;
            try
            {
                webRequest = (HttpWebRequest)WebRequest.Create(url);
                webRequest.Method = "GET";
                webRequest.ProtocolVersion = HttpVersion.Version10;
                webRequest.KeepAlive = false;
                webRequest.Proxy = null;

                using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
                {
                    using (Stream stream = webResponse.GetResponseStream())
                    {
                        sResult = new byte[webResponse.ContentLength];

                        int readecount = 0;
                        while (readecount < (int)webResponse.ContentLength)
                        {
                            readecount += stream.Read(sResult, readecount, (int)webResponse.ContentLength - readecount);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                webRequest?.Abort();
                throw ex;
            }

            return sResult;
        }
    }
}
